package com.zhy.ble.demo.ui;

import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;

import com.bryan.autolayout.AutoLayoutActivity;
import com.bryan.common.utils.WeakHandler;
import com.bryan.common.utils.log.LogUtils;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.AndPermission;
import com.yanzhenjie.permission.runtime.Permission;
import com.zhy.ble.demo.R;
import com.zhy.ble.demo.ToastMgr;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import cn.com.heaton.bleLib.ble.Ble;
import cn.com.heaton.bleLib.ble.L;
import cn.com.heaton.bleLib.ble.callback.BleScanCallback;
import cn.com.heaton.bleLib.ble.model.BleDevice;

/**
 * 1-需要位置权限
 * 2-休要打开GPS/位置服务
 * Created by bryan on 2019/5/16.
 */
public class ZDListActivity extends AutoLayoutActivity {

    private String TAG = ZDListActivity.class.getSimpleName();

    private static final int Msg_Find_Device = 0x606;//发现设备

    //扫描
    private Button btnScan;
    //设备列表
    private ListView mListView;
    //扫描提示
    private LinearLayout llScan;

    private LeDeviceListAdapter mLeDeviceListAdapter;

    private Ble<BleDevice> mBle;
    //已经添加到列表的设备名字
    private List<String> targetDevice = new ArrayList<>();

    /*标识蓝牙是否已经打开 */
    private boolean isBleHasOpen = false;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ble_list);
        findViewById(R.id.iv_back).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        llScan = findViewById(R.id.ll_scan);
        btnScan = findViewById(R.id.btn_scan);
        btnScan.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!isBleHasOpen) {
                    ToastMgr.show("蓝牙状态异常，请检查蓝牙是否已打开");
                    finish();
                    return;
                }
                if (isScaning) {
                    toast("正在扫描中，请稍后");
                    return;
                }
                startScanDevice();
            }
        });

        mListView = findViewById(R.id.listView);
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                final BleDevice device = mLeDeviceListAdapter.getDevice(position);
                if (device == null) return;
                //找到需要的设备，停止设备扫描操作
                stopScanDevices();
                //skip
                Intent intent = new Intent(ZDListActivity.this, BleOperationActivity.class);
                intent.putExtra("BLE", device);
                startActivity(intent);
            }
        });

        mLeDeviceListAdapter = new LeDeviceListAdapter(this);
        mListView.setAdapter(mLeDeviceListAdapter);
        //1、请求蓝牙相关权限
        requestPermission();
    }


    //检查蓝牙是否支持及打开
    private void checkBluetoothStatus() {
        // 检查设备是否支持BLE4.0
        if (!mBle.isSupportBle(this)) {
            ToastMgr.show("当前设备不支持Ble");
            finish();
            return;
        }
        if (!mBle.isBleEnable()) {
            //4、若未打开，则请求打开蓝牙
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, Ble.REQUEST_ENABLE_BT);
        } else {
            //5、若已打开，则进行扫描
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    isBleHasOpen = true;
                    startScanDevice();
                }
            }, 200);

        }
    }


    private WeakHandler mHandler = new WeakHandler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case Msg_Find_Device:
                    BleDevice device = (BleDevice) msg.obj;
                    findBleDevice(device);
                    break;
            }
            return false;
        }
    });

    private void findBleDevice(BleDevice device) {
        synchronized (mBle.getLocker()) {
            if (targetDevice.size() > 0) {
                //过滤已存在的设备
                if (!targetDevice.contains(device.getBleName())) {
                    mLeDeviceListAdapter.addDevice(device);
                    mLeDeviceListAdapter.notifyDataSetChanged();
                    targetDevice.add(device.getBleName());
                }
            } else {
                mLeDeviceListAdapter.addDevice(device);
                mLeDeviceListAdapter.notifyDataSetChanged();
                targetDevice.add(device.getBleName());
            }
        }
    }


    /*上一次扫描的时间，为了限制短时间内不能让用户扫描多次*/
    private long lastScanTime = 0;
    /*是否正在扫描设备*/
    private boolean isScaning = false;

    /**
     * 开始扫描
     */
    private void startScanDevice() {
        if (!isBleHasOpen || mBle == null) {
            toast("蓝牙状态异常，请检查蓝牙后重试");
            finish();
            return;
        }
        long curTime = System.currentTimeMillis();
        if (curTime - lastScanTime > 2000) {
            if (mBle.isNotScanning()) {
                lastScanTime = curTime;
                isScaning = true;
                mLeDeviceListAdapter.clear();
                targetDevice.clear();
//                List<BleDevice> connectedDevices = mBle.getConnetedDevices();
//                if (connectedDevices != null && connectedDevices.size() > 0) {
//                    //已连接的设备添加到列表中
//                    for (int i = 0; i < connectedDevices.size(); i++) {
//                        targetDevice.add(connectedDevices.get(i).getBleName());
//                    }
//                    mLeDeviceListAdapter.addDevices(mBle.getConnetedDevices());
//                }
                //开始继续搜索
                mBle.startScan(scanCallback);
            } else {
                toast("正在扫描中，请稍后");
            }
        } else {
            toast("扫描频率过快，请稍后重试");
        }
    }

    public void toast(String content) {
        ToastMgr.show(content);
    }

    /**
     * 停止扫描
     */
    private void stopScanDevices() {
        isScaning = false;
        if (mBle != null && mBle.isScanning()) {
            mBle.stopScan();
        }
    }

    @Override
    protected boolean isNeedAutoLayout() {
        return true;
    }

    /**
     * 扫描的回调
     */
    BleScanCallback<BleDevice> scanCallback = new BleScanCallback<BleDevice>() {
        @Override
        public void onLeScan(final BleDevice device, int rssi, byte[] scanRecord) {

            if (device == null || TextUtils.isEmpty(device.getBleName()) || !isScaning) {
                return;
            }
            LogUtils.i(TAG, "onLeScan: " + device.getBleAddress());
            //尽量不要在onLeScan回调中做太多的事情。可能会出现异常，让onLeScan尽快的返回
            Message msg = new Message();
            msg.what = Msg_Find_Device;
            msg.obj = device;
            mHandler.sendMessage(msg);
        }

        @Override
        public void onStart() {
            super.onStart();
            //开始扫描
            showLoading();
        }

        @Override
        public void onStop() {
            super.onStop();
            //结束扫描
            L.e(TAG, "onStop: ");
            isScaning = false;
            hideLoading();
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // User chose not to enable Bluetooth.
        if (requestCode == Ble.REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
            finish();
        } else if (requestCode == Ble.REQUEST_ENABLE_BT && resultCode == Activity.RESULT_OK) {
            //6、若打开，则进行扫描
            isBleHasOpen = true;
            mBle.startScan(scanCallback);
        } else if (requestCode == Ble.REQUEST_ENABLE_Permission) {
            requestPermission();
        } else if (requestCode == Ble.REQUEST_ENABLE_GPS) {
            requestGpsService();

        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mBle != null) {
            mBle.destory(getApplicationContext());
        }
    }


    //请求权限
    private void requestPermission() {
        AndPermission.with(ZDListActivity.this)
                .runtime()
                .permission(Manifest.permission.BLUETOOTH_ADMIN,
                        Manifest.permission.ACCESS_COARSE_LOCATION)
                .onGranted(new Action<List<String>>() {
                    @Override
                    public void onAction(List<String> data) {
                        requestGpsService();
                    }
                }).onDenied(new Action<List<String>>() {
            @Override
            public void onAction(List<String> permissions) {
                if (AndPermission.hasAlwaysDeniedPermission(ZDListActivity.this, permissions)) {
                    showSettingDialog(ZDListActivity.this, permissions);
                } else {
                    toast("要想使用");
                    //拒绝就关掉服务
                    finish();
                }
            }
        }).start();
    }

    /**
     * 请求位置服务权限
     */
    private void requestGpsService() {
        if (isGpsEnable(getApplicationContext())) {
            initBle();
        } else {
            //引导打开Ble
            new AlertDialog.Builder(ZDListActivity.this).setCancelable(false)
                    .setTitle("提示")
                    .setMessage("使用蓝牙相关功能需要使用到位置服务，是否前往打开相关权限")
                    .setPositiveButton("前往", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                            startActivityForResult(intent, Ble.REQUEST_ENABLE_GPS);
                        }
                    })
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            finish();
                        }
                    })
                    .show();

        }
    }

    /**
     * 查看GPS是否打开，6.0以上有要求要打开
     *
     * @param context
     * @return
     */
    public static final boolean isGpsEnable(final Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            LocationManager locationManager
                    = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            return gps || network;
        }
        return true;
    }


    /**
     * 请求服务提示
     * Display setting dialog.
     */
    public void showSettingDialog(Context context, final List<String> permissions) {
        List<String> permissionNames = Permission.transformText(context, permissions);
        String message = context.getString(R.string.message_permission_always_failed,
                TextUtils.join("\n", permissionNames));

        new AlertDialog.Builder(context).setCancelable(false)
                .setTitle("提示")
                .setMessage(message)
                .setPositiveButton("设置", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        AndPermission.with(ZDListActivity.this).runtime().setting().start(Ble.REQUEST_ENABLE_Permission);
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        finish();
                    }
                })
                .show();
    }

    //初始化蓝牙
    private void initBle() {
        if (mBle == null) {
            mBle = Ble.options()
                    .setLogBleExceptions(true)//设置是否输出打印蓝牙日志
                    .setThrowBleException(true)//设置是否抛出蓝牙异常
                    .setAutoConnect(false)//设置是否自动连接
                    .setFilterScan(true)//设置是否过滤扫描到的设备
                    .setConnectFailedRetryCount(3)
                    .setConnectTimeout(20 * 1000)//设置连接超时时长
                    .setScanPeriod(1500)//设置扫描时长
                    .setCmdOverTime(6000)//配置指令超时时长
//                    .setUuidService(UUID.fromString("00001919-0000-1000-8000-00805f9b34fb"))//设置主服务的uuid
//                    .setUuidWriteCha(UUID.fromString("00002c2c-0000-1000-8000-00805f9b34fb"))//设置可写特征的uuid
//                    .setUuidReadCha(UUID.fromString("00002c2c-0000-1000-8000-00805f9b34fb"))//设置可读特征值
                    .setUuidService(UUID.fromString("e7810a71-73ae-499d-8c15-faa9aef0c3f2"))//设置主服务的uuid
                    .setUuidReadCha(UUID.fromString("bef8d6c9-9c21-4c9e-b632-bd58c1009f9f"))//设置可读特征值
                    .setUuidWriteCha(UUID.fromString("bef8d6c9-9c21-4c9e-b632-bd58c1009f9f"))//设置可写特征的uuid
                    .create(ZDListActivity.this.getApplicationContext());
        }

        //3、检查蓝牙是否支持及打开
        checkBluetoothStatus();
    }


    public void showLoading() {
        llScan.setVisibility(View.VISIBLE);
        btnScan.setVisibility(View.GONE);
    }

    public void hideLoading() {
        llScan.setVisibility(View.GONE);
        btnScan.setVisibility(View.VISIBLE);
    }


}
